<?php
/**
 * Kits base class
 *
 * This file is part of Webappkit, a packages system for PHP web apps
 * @link http://webappkit.net
 * @package webappkit
 * @author J.Ducastel <nospam0@ducastel.name>
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 */

class WakKit {
    /**
     * @var string kit unique id
     */
    var $_id;

    /**
     * @var array kit configuration data
     */
    var $_cfg=array();

    /**
     * @var string physical path
     */
    var $_path;

    /**
     * constructor
     * @access private
     * @param string kit id
     */
    function WakKit($id) {
        // setting config
        $this->_id=Webappkit::checkID($id);
        $this->_path=webappkit::getPathFromId($id);
        $this->_cfg=webappkit::getCfgFromId($id);
        // setting tool members
        foreach ($this->_cfg['tools'] as $name => $class) {
            $this->_buildTool($name,$class);
        }
    }

    /**
     * this method is the one to be implemented and used for requests handling kits
     * @access public
     * @return bool
     */
    function run() {
        trigger_error("webappkit : kit {$this->_id} is not able to handle requests. method run() not implemented.",E_USER_NOTICE);
        return false;
    }

    /**
     * get kit's path
     * @return string
     */
    function getPath() {
        return $this->_path;
    }

    /**
     * get kit's id
     */
    function getId() {
        return $this->_id;
    }

    /**
     * get kit's config
     * @return array
     */
    function getCfg($key=null) {
        return $this->_cfg;
    }

    /**
     * list subkits
     * @access public
     * @return array kits ids
     */
    function listSubkits() {
        // echo '<p>listing subkits in '.$this->getPath().'</p>';
        return Webappkit::listKits($this->getPath());
    }

    /**
     * get a subkit instance if available
     * @access public
     * @param string subkit id (without the parent part)
     * @return Webappkit
     */
    function getSubkit($id) {
        return Webappkit::getKit($this->getId().'.'.$id);
    }

    /**
     * get kit tools.
     * May filter by class
     * @access public
     * @param string $class if provided, will return only tools from this class
     * @return array name=>instance
     */
    function & getTools($class=null) {
        $tools=array();
        // listing members
        $names=array_keys(get_object_vars($this));
        // print_r($names);
        if ($class) {
            // looping members
            foreach ($names as $name) {
                // echo $name.' : '; print_r($this->$name);
                // checking class
                if (is_a($this->$name,$class))
                    $tools[$name]=&$this->$name;
            }
        } else {
            // looping members
            foreach ($names as $name) {
                // checking class
                if (is_a($this->$name,'wakTool'))
                    $tools[$name]=&$this->$name;
            }
        }
        return $tools;
    }

    /**
     * tells if a tool has its custom config
     * @access public
     * @param string $tool tool's name
     * @return bool
     */
    function toolHasConfig($tool) {
        $file=$this->getPath().$tool.'.tool.ini'; // echo $file;
        return file_exists($file) and is_file($file);
    }

    /**
    * loads tool's config ini file ( {name}.tool.ini )
    * @access protected
    * @param string $name tool's name
    * @return array|null|false
    */
    function _getToolCfg($name) {
        // getting ini file
        $file=$this->getPath().$name.'.tool.ini'; // echo $file;
        if (!file_exists($file) or !is_file($file)) {
            // trigger_error("no config file for tool {$this->_id}->{$name} ($file)");
            return null;
        }
        // parsing, with sections
        $cfg=parse_ini_file($file,true);
        if (!is_array($cfg)) {
            trigger_error("failed to parse $file");
            return false;
        }
        return $cfg;
    }

    /**
     * builds a tool member : create a tool member instance for the kit.
     * Will try to load config from ini file
     * @access protected
     * @param string $name the member name given to tool
     * @param string $class
     * @return bool
     */
    function _buildTool($name,$class) {
        // defining class
        if (!class_exists($class)) {
            trigger_error("failed to build tool $name for kit {$this->_id} : class $class is missing",E_USER_WARNING);
            return false;
        }
        // trying to read config from ini file within self kit
            $cfg=$this->_getToolCfg($name);
        // calling factory method
            // $instance=$class::factory($this,$name);
        $instance=call_user_func(array($class,'toolFactory'),$this->_id,$cfg);
        $this->$name=&$instance;
        return true;
    }
}
